/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 - 2008 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.basics.bean.impl;

import java.io.File;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.activation.FileTypeMap;

import com.genia.toolbox.basics.bean.ContentTypeChecker;

/**
 * implementation of {@link FileTypeMap} that get its data from either the
 * default content types of a {@link Map} that binds file prefix to mime content
 * type.
 */
public class DefaultFileTypeMap
    extends FileTypeMap
    implements ContentTypeChecker
{

  /**
   * the default {@link FileTypeMap}.
   */
  private transient final FileTypeMap delegateFileTypeMap = FileTypeMap.getDefaultFileTypeMap();

  /**
   * the {@link Map} that binds file prefix to MIME content type.
   */
  private Map<String, String> fileTypeMap = new HashMap<String, String>();



  /**
   * constructor.
   */
  public DefaultFileTypeMap()
  {
    FileTypeMap.setDefaultFileTypeMap(this);
  }



  /**
   * Return the type of the file object. This method should always return a
   * valid MIME type.
   * 
   * @param file
   *          A file to be typed.
   * @return The content type.
   */
  @Override
  public String getContentType(File file)
  {
    String contentType = delegateFileTypeMap.getContentType(file);
    if (!isResolved(contentType)) {
      return getContentType(file.getName());
    }
    return contentType;
  }



  /**
   * Return the type of the file passed in. This method should always return a
   * valid MIME type.
   * 
   * @param filename
   *          the pathname of the file.
   * @return The content type.
   */
  @Override
  public String getContentType(String filename)
  {
    String contentType = delegateFileTypeMap.getContentType(filename);
    if (!isResolved(contentType)) {
      int index = filename.lastIndexOf('.');
      if (index != -1) {
        String suffix = filename.substring(index + 1).toLowerCase(Locale.getDefault());
        String newContentType = getFileTypeMap().get(suffix);
        if (newContentType != null)
          return newContentType;
      }
    }

    return contentType;
  }



  /**
   * return whether the result content-type from the previous default file type
   * map is accepted or not.
   * 
   * @param contentType
   *          the content-type to examine
   * @return <code>true</code> if and only if the content-type is resolved
   * @see com.genia.toolbox.basics.bean.ContentTypeChecker#isResolved(java.lang.String)
   */
  public boolean isResolved(final String contentType)
  {
    return (!"application/octet-stream".equals(contentType)) && getFileTypeMap() != null;
  }



  /**
   * returns whether the content type is a standard one.
   * 
   * @param contentType
   *          the content-type to check
   * @return <code>true</code> if and only if the content-type is standard
   * @see com.genia.toolbox.basics.bean.ContentTypeChecker#isStandard(java.lang.String)
   */
  public boolean isStandard(final String contentType)
  {
    return (getFileTypeMap() != null) && (getFileTypeMap().containsValue(contentType));
  }



  /**
   * getter for the fileTypeMap property.
   * 
   * @return the fileTypeMap
   */
  public Map<String, String> getFileTypeMap()
  {
    return fileTypeMap;
  }



  /**
   * setter for the fileTypeMap property.
   * 
   * @param fileTypeMap
   *          the fileTypeMap to set
   */
  public void setFileTypeMap(Map<String, String> fileTypeMap)
  {
    this.fileTypeMap = fileTypeMap;
  }

}
